//
//  ModalView.swift
//  Automobile
//
//  Created by erkebulan elzhan on 8/2/20.
//  Copyright © 2020 erkebulan elzhan. All rights reserved.
//

import UIKit
import SnapKit



protocol ModalViewDelegate {
    func onCancel ()
    func onSubmit (for type: ModalView.ModalType, data: Any)
    func showError (_ title: String, _ message: String)
}

final class ModalView: UIView {
    
    // MARK: - Outlets
    
    private lazy var titleLbl: UILabel = {
        let lbl = UILabel()
        lbl.font = UIFont.systemFont(ofSize: 20, weight: .bold)
        lbl.textColor = .black
        lbl.textAlignment = .left
        lbl.sizeToFit()
        return lbl
    }()

    private lazy var closeBtn: UIButton = {
        let btn = UIButton()
        btn.setImage(UIImage(named: "dismiss"), for: .normal)
        return btn
    }()
    
    private lazy var resetBtn: UIButton = {
        let btn = UIButton()
        btn.clipsToBounds = true
        btn.layer.cornerRadius = 15
        btn.backgroundColor = .whiteBlueColor
        btn.setTitleColor(.greyColor, for: .normal)
        btn.setTitle("Сбросить", for: .normal)
        return btn
    }()
    
    private lazy var readyBtn: UIButton = {
        let btn = UIButton()
        btn.clipsToBounds = true
        btn.layer.cornerRadius = 15
        btn.backgroundColor = .blueColor
        btn.setTitleColor(.white, for: .normal)
        btn.setTitle("Готово", for: .normal)
        return btn
    }()
    
    private lazy var tableView: UITableView = {
        let table = UITableView()
        table.delegate = self
        table.dataSource = self
        table.register(ModalViewCell.self, forCellReuseIdentifier: "ModalViewCell")
        table.showsVerticalScrollIndicator = false
        return table
    }()
    
    private lazy var pickerView: UIPickerView = {
        let picker = UIPickerView()
        picker.delegate = self
        picker.dataSource = self
        return picker
    }()
    
    private lazy var rangeView = RangeView()
    
    private lazy var spinner = SpinnerView()
    
    // MARK: - Props
    
    enum ModalType: String, CaseIterable {
        case price = "Цена"
        case year = "Год"
        case korobka = "Коробка"
        case kuzov = "Кузов"
        case dvigatel = "Двигатель"
        case volume = "Объем двигателя, л."
        case privod = "Привод"
        case power = "Мощность"
        case probeg = "Пробег, км"
        case expenditures = "Расход на 100 км, л."
        case color = "Цвет"
        case rule = "Расположение руля"
        
        case state = "Состояние"
        case monthPurchase = "Ежемесячный платеж"
        case firstPurchase = "Первоначальный платеж"
    }
    
    struct ModalData: Decodable {
        var name: String
        var isSelected: Bool?=false
        var color: UIColor?=nil
        var id: Int?=nil
        
        enum CodingKeys: CodingKey {
            case name, id, type
        }
        
        init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            if let _name = try? values.decode(String.self, forKey: .name) {
                self.name = _name
            } else {
                self.name = (try? values.decode(String.self, forKey: .type)) ?? ""
            }
            
            self.id = try values.decode(Int.self, forKey: .id)
        }
        
        init (name: String, color: UIColor?=nil) {
            self.name = name
            self.color = color
        }
    }
    
    private var viewModel = ModalViewModel()
    private var modalType: ModalType!
    private var isMultiSelect: Bool = true
    private var lastSelectedRow: Int?
    
    
    var delegate: ModalViewDelegate!
    
    
    
    // MARK:- Init
    
    init(isMultiSelect: Bool = true) {
        super.init(frame: .zero)
        self.isMultiSelect = isMultiSelect
        self.addView()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    /// Reloading view
    /// - Parameter type: [probeg, power, year]
    
    func updateModalType(type: ModalType) {
        
        // if need to be fetched from server
        
        let noFetch:[ModalType] = [ .probeg, .power, .year, .volume, .expenditures, .price, .monthPurchase, .firstPurchase ]
           
        if !(noFetch.contains(type)) {
            self.loadData(type: type)
        }
        
        self.modalType = type
        self.titleLbl.text = type.rawValue
        
        if type == .price || type == .monthPurchase || type == .firstPurchase {
            self.addRangeView()
        } else if viewModel.pickerData[type] != nil {
            self.addPickerView()
        }
        else {
            self.addTableView()
        }
        self.bringSubviewToFront(spinner)
    }
    
    
    /// Loading data source from backend
    /// - Parameter type: [probeg, power, year]
    private func loadData (type: ModalType) {
        self.spinner.startAnimating()
        self.isUserInteractionEnabled = false
        self.viewModel.loadData(modal: type) { (error) in
            self.isUserInteractionEnabled = true
            if ((error) != nil) {
                print(error)
            } 
            self.tableView.reloadData()
            self.spinner.stopAnimating()
        }
    }
}


// MARK: - Actions

extension ModalView {
    
    /// Return initial values
    /// - Parameter sender: Сбросить button
    @objc func onReset (sender: UIButton) {
        if modalType == ModalType.power {
            
        } else {
            viewModel.resetModal(type: modalType)
            self.tableView.reloadData()
        }
    }
    
    /// Hide Modal View
    /// - Parameter sender: Назад button
    @objc func onCancel (sender: UIButton) {
        delegate.onCancel()
    }
    
    /// Send data to Filter View Controller
    /// - Parameter sender: Готово button
    @objc func onReady (sender: UIButton) {
        
        // Range Sliders
        if modalType == ModalView.ModalType.price || modalType == ModalView.ModalType.monthPurchase || modalType == ModalView.ModalType.firstPurchase {
            
            let valid = rangeView.getUpper() > rangeView.getLower()
            
            if valid {
                let data = [Double(rangeView.getLower()), Double(rangeView.getUpper())]
                delegate.onSubmit(for: modalType, data: data)
            } else {
                
            }
        } else if viewModel.pickerData[modalType] != nil {
            
            // Picker View
            let ot = pickerView.selectedRow(inComponent: 0)
            let _do = pickerView.selectedRow(inComponent: 1)
            
            if _do > ot || _do == 0 {
                var items:[Double?]!
                items = [ot == 0 ? nil : viewModel.pickerData[modalType]![ot - 1], _do == 0 ? nil : viewModel.pickerData[modalType]![_do - 1]]
                delegate.onSubmit(for: modalType, data: items as Any)
            } else {
                delegate.showError("Упс...", "До должен быть больше от")
            }
            
        } else {
            let data = viewModel.modalData[modalType]!.filter { $0.isSelected == true }
            delegate.onSubmit(for: modalType, data: data)
        }
    }
}



// MARK: - UITableView Delegate/DataSource

extension ModalView: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        if !isMultiSelect && lastSelectedRow != nil {
            viewModel.modalData[modalType]![lastSelectedRow!].isSelected = false
            tableView.reloadRows(at: [IndexPath(item: lastSelectedRow!, section: 0)], with: .fade)
        }
        
        viewModel.modalData[modalType]![indexPath.row].isSelected?.toggle()
        self.tableView.reloadRows(at: [indexPath], with: .right)
        lastSelectedRow = indexPath.row
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return (viewModel.modalData[modalType] ?? []).count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ModalViewCell") as! ModalViewCell
        cell.data = (viewModel.modalData[modalType] ?? [])[indexPath.row]
        cell.selectionStyle = .none
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80
    }
    
}

// MARK: - UIPickerView Delegate/DataSource

extension ModalView: UIPickerViewDelegate, UIPickerViewDataSource {
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if (row == 0) {
            return ["от", "до"][component]
        } else {
            let intValue = Int(viewModel.pickerData[modalType]![row-1])
            return modalType == .volume ? "\(viewModel.pickerData[modalType]![row-1])" : "\(intValue)"
        }
    }
    
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 2
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return viewModel.pickerData[modalType]!.count + 1
    }
}

// MARK: - UI Functions


extension ModalView {
    
    private func addView () {
        self.backgroundColor = .white
        
        // Adding shadow
        self.layer.shadowOffset = CGSize(width: 0, height: -25)
        self.layer.shadowRadius = 40
        self.layer.shadowColor = UIColor.black.cgColor
        self.layer.shadowOpacity = 0.18
        
        // adding all views, except table view and picker view
        self.addSubview(closeBtn)
        self.addSubview(titleLbl)
        self.addSubview(resetBtn)
        self.addSubview(readyBtn)
        self.addSubview(spinner)
        
        // onClick methods for all 3 buttons
        closeBtn.addTarget(self, action: #selector(onCancel(sender:)), for: .touchUpInside)
        resetBtn.addTarget(self, action: #selector(onReset(sender:)), for: .touchUpInside)
        readyBtn.addTarget(self, action: #selector(onReady(sender:)), for: .touchUpInside)

        self.addConstraints()
    }
    
    private func addConstraints () {
        self.closeBtn.snp.makeConstraints { (make) in
            make.top.equalToSuperview().inset(28)
            make.width.height.equalTo(16)
            make.trailing.equalToSuperview().offset(-16)
        }
        self.titleLbl.snp.makeConstraints { (make) in
            make.leading.equalToSuperview().offset(16)
            make.centerY.equalTo(closeBtn)
        }
        self.resetBtn.snp.makeConstraints { (make) in
            make.leading.equalTo(titleLbl)
            make.height.equalTo(44)
            make.trailing.equalTo(readyBtn.snp.leading).offset(-8)
            make.bottom.equalToSuperview().offset(-16)
        }
        self.readyBtn.snp.makeConstraints { (make) in
            make.trailing.equalTo(closeBtn)
            make.height.equalTo(44)
            make.width.equalTo(resetBtn)
            make.bottom.equalToSuperview().offset(-16)
        }
        self.spinner.snp.makeConstraints { (make) in
            make.width.height.equalTo(50)
            make.center.equalToSuperview()
        }
    }
    
    
    /// Remove picker view and add table view
    private func addTableView () {
        pickerView.removeFromSuperview()
        rangeView.removeFromSuperview()
        self.addSubview(tableView)
        tableView.snp.makeConstraints { (make) in
            make.leading.trailing.equalToSuperview().inset(16)
            make.top.equalTo(titleLbl.snp.bottom).offset(20)
            make.bottom.equalTo(resetBtn.snp.top).offset(-20)
        }
        tableView.reloadData()
    }
    /// Remove table view and add picker view
    private func addPickerView () {
        tableView.removeFromSuperview()
        rangeView.removeFromSuperview()
        self.addSubview(pickerView)
        pickerView.snp.makeConstraints { (make) in
            make.leading.trailing.equalToSuperview().inset(16)
            make.top.equalTo(titleLbl.snp.bottom).offset(20)
            make.bottom.equalTo(resetBtn.snp.top).offset(-20)
        }
        pickerView.reloadAllComponents()
    }
    
    /// Price Range View With slider and two labels
    private func addRangeView () {
        tableView.removeFromSuperview()
        pickerView.removeFromSuperview()
        self.addSubview(rangeView)
        rangeView.setMaxMin(max: 10000000, min: 0)
        
        rangeView.snp.makeConstraints { (make) in
            make.leading.trailing.equalToSuperview().inset(16)
            make.top.equalTo(titleLbl.snp.bottom).offset(20)
            make.bottom.equalTo(resetBtn.snp.top).offset(-20)
        }
    }
}
